---
slug: /api/ide-integration
---




import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# IDE Integration

Dagger uses GraphQL as its low-level language-agnostic API query language, and each Dagger SDK generates native code-bindings for all dependencies from this API. This gives you all the benefits of type-checking, code completion and other IDE features for your favorite language when developing Dagger Functions.

The `dagger develop` command bootstraps a Dagger module template in the selected programming language and sets up or updates all the resources needed to develop a module. After running this command, follow the steps below to have your IDE recognize the Dagger module.

<Tabs groupId="language" queryString="sdk">
<TabItem value="go" label="Go">
To get your IDE to recognize a Dagger Go module, [configure your `go.work` file](./module-structure.mdx#language-native-packaging) to include the path to your module.

When you generate a Dagger module for the first time, Dagger will create a `go.mod` file just for the module. If the module exists in a sub-directory of an outer Go project (such as `dagger/`, the default), this might confuse the IDE.

If there is already a `go.mod` in the parent directory that you would like to use instead, delete the newly-generated `go.mod` and `go.sum` and Dagger will use the parent one instead. This is not advisable if your Dagger module has certain dependencies that are not relevant to your core product, since most consumers will prefer a narrower set of dependencies.

To keep the generated `go.mod` file and edit your Dagger module in the same IDE session as your project code, one option is to set up a [Go workspace](https://go.dev/doc/tutorial/workspaces):

```shell
# in the root of your repository
go work init
go work use ./
go work use ./path/to/mod
```

After restarting the IDE, you should be able to use IDE features such as go-to-definition, even when editing `dagger/main.go` from the project root.

In most cases, `go.work` should not be committed to the repository, so it is advisable to add it to the project's `.gitignore` file:

```shell
echo go.work >> .gitignore
echo go.work.sum >> .gitignore
```

:::tip
You can also choose to omit the local Go files generated by `dagger develop` from your version control system, as they aren't required to run the module.
:::

When working with multiple inter-dependent Dagger modules, it can be challenging to navigate between Dagger Functions defined in different modules. Source-maps offer a solution to this problem, by allowing developers to directly click through or navigate to type declarations in their IDE.

The Go SDK automatically attaches source-maps to the module code. These are a record of the filename, the line number, and the column number that a type declaration corresponds to in the source code. The SDK analyzes the source code, and outputs these (as line comments of the form `./path/to/filename:line`) when creating the type definitions during module initialization.

Most popular IDEs support source-maps, either natively or with an external plugin, such as the [Open file plugin](https://marketplace.visualstudio.com/items?itemName=Fr43nk.seito-openfile) for Visual Studio Code.
</TabItem>
<TabItem value="python" label="Python">
To get your IDE to recognize a Dagger Python module and any added Dagger module dependencies in the generated client, all dependencies must be installed in an activated [virtual environment](https://packaging.python.org/en/latest/tutorials/installing-packages/#creating-virtual-environments) (for example, in `.venv`, next to `pyproject.toml`). This can either be done manually or transparently by a package manager.

For example, to open the Visual Studio Code from the terminal, with functioning autocompletions (assuming the [Python extensions](https://github.com/microsoft/vscode-python) are installed):

```shell
dagger develop
uv run code .
```

For NeoVim, just replace `code` with `vim`, or any other terminal based editor.

:::note
The `uv run` command works with a `uv.lock` file. If you need to use a `requirements.lock` or other, continue reading for more examples.
:::

## Project environment

The following examples show how to get a working [project environment](https://docs.astral.sh/uv/concepts/projects/#project-environments) (`.venv`) from the terminal, just make sure you run `dagger develop` first, to get the necessary `sdk` directory locally.

<Tabs groupId="pytools">
<TabItem value="uv">

When using a `uv.lock`:

```shell
uv sync
```

If you have an older Dagger module, without a `uv.lock` file, you can create it with:

```shell
uv add --editable ./sdk
rm requirements.lock
````

:::note
uv with `uv.lock` needs to have the SDK library (`dagger-io`, generated in `./sdk`) defined as a production dependency, unlike the other installation methods where it should be a development dependency.
:::

</TabItem>
<TabItem value="uv pip">

When using a `requirements.lock` file, uv provides a ["pip interface"](https://docs.astral.sh/uv/pip/) that replaces multiple tools, while still being much faster. It can manage the Python installation, virtual environment creation, and dependency installation.

For example:

```shell
uv venv
uv pip install -r requirements.lock -e ./sdk -e .
```

:::note
By default, `uv venv` will create an environment with Python 3.12. To pin Python 3.11 both locally and in Dagger, run this first:

```shell
echo 3.11 > .python-version
```

:::

</TabItem>
<TabItem value="pip">

Make sure you have the same Python version that Dagger uses first. By default it's Python 3.12, unless it's overridden in `pyproject.toml` or in `.python-version`.

```shell
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.lock -e ./sdk -e .
```

</TabItem>
<TabItem value="hatch">

First, update `pyproject.toml` to [allow direct references](https://hatch.pypa.io/latest/config/metadata/#allowing-direct-references), and add the [local](https://hatch.pypa.io/latest/config/dependency/#local) SDK library (`dagger-io`) as a  `dev` dependency:

```toml
[project]
name = "main"
version = "0.0.0"

[tool.hatch.metadata]
allow-direct-references = true

[tool.hatch.envs.dev]
dependencies = [
  "dagger-io @ {root:uri}/sdk",
]
```

Then, open the editor with the `dev` [Hatch environment](https://hatch.pypa.io/latest/config/environment/overview/):

```shell
hatch run dev:vim .
```

:::note
Hatch manages the project environment in a central location by default instead of `.venv`.
:::

</TabItem>
<TabItem value="poetry">

First, add `./sdk` as a development dependency:

```shell
poetry add --group=dev -e ./sdk
```

Then, open the editor with:

```shell
poetry run vim .
```

:::note
Poetry manages the project environment in a central location instead of `.venv`.
:::

</TabItem>
</Tabs>

:::tip
If you place the virtual environment (`.venv`) inside the module, don't forget to add it to `.gitignore` and to `"include": ["!.venv"]` in `dagger.json` to avoid uploading those files to the runtime container unnecessarily.
:::

<Tabs>
<TabItem value="Visual Studio Code">

The simplest way to get [autocompletions and IntelliSense](https://code.visualstudio.com/docs/python/editing#_autocomplete-and-intellisense) working is to open it with the directory that has `.venv` (next to `.pyproject.toml`), because the IDE picks it up automatically when it's in the root of the [workspace](https://code.visualstudio.com/docs/python/python-tutorial#_start-vs-code-in-a-workspace-folder):

```shell
code .
```

VS Code doesn't need to be opened from the terminal though. The same directory can be opened with VS Code's **File > Open Folder** from the graphical interface (GUI).

The virtual environment can also be created and managed from within the IDE instead of from the terminal, if it supports the chosen lock file format. To know more, see [Visual Studio Code Python Environments](https://code.visualstudio.com/docs/python/environments).
</TabItem>
<TabItem value="PyCharm">
PyCharm is a very popular IDE for Python projects. The simplest way for PyCharm to recognize the `dagger` package is to open the IDE in the directory that has `.venv` and `pyproject.toml`, via the terminal or the GUI.

It can also create and manage the project environment, but may not support `uv.lock` yet, so best run `uv` from the terminal instead.
</TabItem>
</Tabs>

</TabItem>
<TabItem value="typescript" label="TypeScript">

When opening the generated `dagger/src/index.ts` in an IDE, most IDEs will automatically recognize the `@dagger.io/dagger` package, so long as the `tsconfig.json` file has a path configured on it.

For Dagger modules initialized using `dagger init`, the default template is already configured this way:

```json
    "experimentalDecorators": true,
    "paths": {
      "@dagger.io/dagger": ["./sdk"]
    }
```

This configuration doesn't require separate installation of the dependency to enable type-hinting or other IDE features.

When working with multiple inter-dependent Dagger modules, it can be challenging to navigate between Dagger Functions defined in different modules. Source-maps offer a solution to this problem, by allowing developers to directly click through or navigate to type declarations in their IDE.

The TypeScript SDK automatically attaches source-maps to the module code. These are a record of the filename, the line number, and the column number that a type declaration corresponds to in the source code. The SDK analyzes the source code, and outputs these (as line comments of the form `./path/to/filename:line`) when creating the type definitions during module initialization.

Most popular IDEs support source-maps, either natively or with an external plugin, such as the [Open file plugin](https://marketplace.visualstudio.com/items?itemName=Fr43nk.seito-openfile) for Visual Studio Code.
</TabItem>
<TabItem value="php" label="PHP">
To get your IDE to recognize a Dagger PHP module, ensure your `composer.json` has a path configured to the generated `dagger/dagger` package. This is located in the `sdk` directory of your module.

For Dagger modules initialized using `dagger init`, the default template is already configured this way:

```json
"repositories": [
  {
    "type": "path",
    "url": "./sdk"
  }
],
"require": {
  "dagger/dagger": "*@dev"
},
```

To get autocompletions and IntelliSense, the setup will vary depending on your IDE.

<Tabs>
<TabItem value="PhpStorm">
PhpStorm is a very popular IDE for PHP projects. The simplest way for PhpStorm to recognize the `dagger` package is to open the IDE in the directory containing your module's `composer.json` file. You may also open it from any parent directory, such as a project containing the dagger module.

</TabItem>
<TabItem value="Visual Studio Code">

The simplest way to get autocompletions and IntelliSense working is to install the [Intelephense](https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client) or the [Phpactor](https://marketplace.visualstudio.com/items?itemName=phpactor.vscode-phpactor) extension.

Then open Visual Studio Code in the directory containing your module's `composer.json` file. You may also open it from any parent directory, such as a project containing the dagger module.

</TabItem>
<TabItem value="Emacs">
The simplest way to get to get autocompletions and IntelliSense working is to use the built-in LSP client [Eglot](https://github.com/joaotavora/eglot).

A PHP LSP (Language Server Protocol) will need to be installed separately such as [Phpactor](https://github.com/phpactor/phpactor).

You may also want to install [PHP Mode](https://github.com/emacs-php/php-mode) for syntax highlighting and indentation.

Assuming you've installed the above, adding the following snippet to your `init.el` file will automatically enable autocompletion and Intellisense when opening PHP files.

```lisp
(require 'eglot)
(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs
               '(php-mode . "phpactor"))
  (add-hook 'php-mode-hook 'eglot-ensure))
```

Then open Emacs in any file within the scope of your module's `composer.json` file.

</TabItem>
</Tabs>
</TabItem>
<TabItem value="java" label="Java">
When you generate a Dagger Java module, a `pom.xml` file is created in the module directory. For example, for a module name
`your-module`, the example source code is created under `src/main/java/io/dagger/modules/yourmodule/YourModule.java`.

The Dagger dependency code, especially the code generated based on the Dagger engine version and the different module
dependencies you can have, is available under `target/generated-sources`.

This creates a standard Maven project structure, and you can import the project into your favorite IDE as a Maven project.
The IDE will automatically recognize the Dagger dependencies and provide code completion and other features out of the box.

:::tip
The `target` directory is added to the `.gitignore` file by default, so you don't need to worry about committing the generated code.
This code is only to help the IDE provide code completion and other features. This code is not required to run the module.
It can be refreshed by running `dagger develop` again.
:::

Most popular IDEs, like IntelliJ Idea or Visual Studio Code, support Maven projects, and will provide out-of-the-box code completion.

:::note
The provided `pom.xml` configures the `maven-compiler-plugin` to run the Dagger-specific annotation processor and the
`maven-shade-plugin` to set the main class for the module and `build-helper-maven-plugin` to add generated Java files
as sources to help for code completion. These configurations are necessary for the module to function correctly and
should not be modified (although you can freely update other parts of the `pom.xml` file).
:::
</TabItem>
</Tabs>
